﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PerCederberg.Grammatica.Runtime;

namespace SafeScript.MetaModel
{
    public class Class : AbstractType
    {
        /// <summary>
        /// Used for caching
        /// </summary>
        private object constructor;

        public bool IsSealed;
        public bool IsAbstract;

        //public override ITypeDef Instantiate(Dictionary<TemplateParameterType,ITypeDef> templateArguments)
        //{
        //    if (this.TemplateParameters.Count == 0)
        //        return this;
        //    return Compiler.CurrentCompiler.GetTemplateInstance(this, templateArguments);
        //}

        //protected internal override void InstantiateIntern(AbstractType instance, List<TemplateParameterType> templateParams, List<ITypeDef> templateArguments)
        //{
        //    base.InstantiateIntern(instance, templateParams, templateArguments);
        //    (instance as Class).IsSealed = this.IsSealed;
        //    (instance as Class).IsAbstract = this.IsAbstract;
        //}

        public Class BaseClass
        {
            get
            {
                if (this.BaseTypes.Count > 0 && this.BaseTypes[0] is Class)
                    return this.BaseTypes[0] as Class;
                return null;
            }
            set
            {
                System.Diagnostics.Debug.Assert(this.BaseClass == null);
                this.BaseTypes.Insert(0, value);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns>Constructor or MemberFunctionSet</returns>
        public object GetConstructor()
        {
            // Cached?
            if (this.constructor != null)
                return this.constructor;

            this.constructor = this.GetScopeElement("ctor");
            // No constructor specified?
            if (this.constructor == null )
                // Create a default constructor
                this.constructor = new Constructor() { Name = "ctor", ReturnType = new InstanceType() { Type = this }, Owner = this, IsGenericConstructor = true };
            return this.constructor;
        }

        public Constructor GetDefaultConstructor()
        {
            // There must exist a constructor which takes no parameters
            object c = this.GetConstructor();
            Constructor ctor = c as Constructor;
            if ( ctor != null )
            {
                if ( ctor.Parameters.Count == 0 )
                    return ctor;
                return null;
            }

            if (c is MemberFunctionSet)
            {
                foreach (MemberFunction f in (c as MemberFunctionSet).Functions)
                {
                    if (f.ParameterTypes.Count == 0)
                        return f as Constructor;
                }
            }

            return null;
        }
    }
}
